package org.linlinjava.litemall.wx.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.paypal.api.payments.Links;
import com.paypal.api.payments.Payment;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.linlinjava.litemall.core.notify.AwsNotifyService;
import org.linlinjava.litemall.core.notify.NoticeHelper;
import org.linlinjava.litemall.core.util.RegexUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.validator.Order;
import org.linlinjava.litemall.core.validator.Sort;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.wx.annotation.LogAnno;
import org.linlinjava.litemall.wx.annotation.LoginUser;
import org.linlinjava.litemall.wx.constant.LitemallWXConstants;
import org.linlinjava.litemall.wx.dto.*;
import org.linlinjava.litemall.wx.manage.WxNewSubscribeManageService;
import org.linlinjava.litemall.wx.service.WxNewSubscribeService;
import org.linlinjava.litemall.wx.service.WxShopService;
import org.linlinjava.litemall.wx.util.LocationUtils;
import org.linlinjava.litemall.wx.util.PageUtil;
import org.linlinjava.litemall.wx.util.URLUtils;
import org.linlinjava.litemall.wx.vo.LumiereSubscribeUserLogVo;
import org.linlinjava.litemall.wx.vo.SubscribeListVo;
import org.linlinjava.litemall.wx.vo.SubscribeUserListVo;
import org.linlinjava.litemall.wx.vo.SubscribeUserVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static org.linlinjava.litemall.db.beans.Constants.*;
import static org.linlinjava.litemall.wx.util.WxResponseCode.*;
import static org.linlinjava.litemall.wx.util.WxResponseEnum.NOT_ENOUGH_AMOUNT;
/**
 * wx新订阅控制器
 *
 * @author yliyun
 * @date 2022/09/14
 */
@Slf4j
@Api(tags = "创建新订阅API")
@RestController
@RequestMapping("/wx/newSubscribe")
@Validated
public class WxNewSubscribeController {

    /**
     * 卢米埃订阅服务
     */
    @Autowired
    private LumiereSubscribeService lumiereSubscribeService;

    /**
     * 卢米埃subscirbe商品服务
     */
    @Autowired
    private LumiereSubscirbeGoodsService lumiereSubscirbeGoodsService;

    /**
     * 卢米埃订阅规则服务
     */
    @Autowired
    private LumiereSubscribeRuleService lumiereSubscribeRuleService;

    /**
     * litemall用户服务
     */
    @Autowired
    private LitemallUserService litemallUserService;

    /**
     * litemall礼品卡用户服务
     */
    @Autowired
    private LitemallGiftCardUserService litemallGiftCardUserService;

    /**
     * litemall地址服务
     */
    @Autowired
    private LitemallAddressService litemallAddressService;

    /**
     * litemall店服务
     */
    @Autowired
    private LitemallShopService litemallShopService;


    /**
     * 卢米埃订阅用户服务
     */
    @Autowired
    private LumiereSubscribeUserService lumiereSubscribeUserService;

    /**
     * 卢米埃订阅用户日志服务
     */
    @Autowired
    private LumiereSubscribeUserLogService lumiereSubscribeUserLogService;

    /**
     * litemall商品服务
     */
    @Autowired
    private LitemallGoodsService litemallGoodsService;

    /**
     * litemall店地区服务
     */
    @Autowired
    private LitemallShopRegionService litemallShopRegionService;

    /**
     * 地区服务
     */
    @Autowired
    private LitemallRegionService regionService;

    /**
     * 商品地区服务
     */
    @Autowired
    private LitemallGoodsRegionService goodsRegionService;

    /**
     * litemall税务服务
     */
    @Autowired
    private LitemallTaxService litemallTaxService;

    /**
     * 卢米埃订阅用户订单服务
     */
    @Autowired
    private LumiereSubscribeUserOrderService lumiereSubscribeUserOrderService;

    /**
     * litemall商品规范服务
     */
    @Autowired
    private LitemallGoodsSpecificationService litemallGoodsSpecificationService;

    /**
     * litemall货物产品服务
     */
    @Autowired
    private LitemallGoodsProductService litemallGoodsProductService;

    /**
     * 订单服务
     */
    @Autowired
    private LitemallOrderService orderService;
    /**
     * 货物税服务
     */
    @Autowired
    private GoodsTaxService goodsTaxService;
    /**
     * litemall订货服务
     */
    @Autowired
    private LitemallOrderGoodsService litemallOrderGoodsService;

    /**
     * wx店服务
     */
    @Autowired
    private WxShopService wxShopService;

    /**
     * litemall充电消费服务
     */
    @Autowired
    private LitemallRechargeConsumptionService litemallRechargeConsumptionService;

    /**
     * 完整日志服务
     */
    @Autowired
    private LitemallIntegralLogService integralLogService;

    /**
     * litemall礼品卡用户日志服务
     */
    @Autowired
    private LitemallGiftCardUserLogService litemallGiftCardUserLogService;

    /**
     * 注意助手
     */
    @Autowired
    private NoticeHelper noticeHelper;

    /**
     * url跑龙套
     */
    @Autowired
    private URLUtils urlUtils;

    /**
     * aws通知服务
     */
    @Autowired
    private AwsNotifyService awsNotifyService;

    /**
     * 订阅用户订单服务
     */
    @Autowired
    private SubscribeUserOrderService subscribeUserOrderService;


    @Autowired
    private WxNewSubscribeService wxNewSubscribeService;

    @Autowired
    private WxNewSubscribeManageService wxNewSubscribeManageService;


    /**
     * 预付款订单
     * litemall_order订单  lumiere_subscribe_user订阅用户  lumiere_subscribe_user_log订阅用户记录
     * lumiere_subscribe_user_order 订阅用户订单  lumiere_subscribe订阅表 lumiere_subscribe_rule订阅配送规则表  lumiere_subscribe_goods订阅商品关系表 litemall_goods商品基本信息表
     * <p>
     * 创建订阅预支付订单 -》
     *
     * @param userId                      用户id
     * @param subscribePayAfterSuccessDto 订阅成功后支付dto
     * @return {@link ResponseUtil.Response}
     */
    @ApiOperation(value = "创建订阅预支付订单")
    @PostMapping
    @LogAnno
    public ResponseUtil.Response advancePaymentOrder(@LoginUser Integer userId,@RequestBody SubscribePayAfterSuccessDTO subscribePayAfterSuccessDto){
        return wxNewSubscribeService.advancePaymentOrder(userId,subscribePayAfterSuccessDto);
    }


    /**
     * 订阅支付前页面吊起
     * 支付成功后
     *
     * @param userId           用户id
     * @param resp             分别地
     * @param subscribeOrderId 订阅订单id
     * @return {@link Object}
     */
    @ApiOperation(value = "付款准备(给自己购买)")
    @GetMapping(value = {"payAfterSuccess"})
    @LogAnno
    @SneakyThrows
    public Object payAfterSuccess(@LoginUser Integer userId, HttpServletResponse resp,@NotNull @RequestParam Long subscribeOrderId){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        Object obj = wxNewSubscribeService.payAfterSuccess(userId,subscribeOrderId);
        if(!(obj instanceof Payment)){
            return obj;
        }
        Payment payment = (Payment)obj;
        for(Links links : payment.getLinks()){
            if(links.getRel().equals("approval_url")){
                resp.sendRedirect(links.getHref().toString());
                return "redirect:" + links.getHref();
            }
        }
        return "<script type=\"text/javascript\">location.href=\"/\"</script>" ;
    }


    /**
     * givee支付成功后 订阅支付前页面吊起
     * 支付成功后
     *
     * @param userId           用户id
     * @param resp             分别地
     * @param subscribeOrderId 订阅订单id
     * @return {@link Object}
     */
    @ApiOperation(value = "付款准备(赠送)")
    @GetMapping(value = {"payGiveeAfterSuccess"})
    @LogAnno
    @SneakyThrows
    public Object payGiveeAfterSuccess(@LoginUser Integer userId,String message, HttpServletResponse resp,@NotNull @RequestParam Long subscribeOrderId){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        Object obj = wxNewSubscribeService.payGiveeAfterSuccess(userId,subscribeOrderId,message);
        if(!(obj instanceof Payment)){
            return obj;
        }
        Payment payment = (Payment)obj;
        for(Links links : payment.getLinks()){
            if(links.getRel().equals("approval_url")){
                resp.sendRedirect(links.getHref().toString());
                return "redirect:" + links.getHref();
            }
        }
        return "<script type=\"text/javascript\">location.href=\"/\"</script>" ;
    }

    /**
     * 支付成功后
     *
     * @param paymentId 支付id
     * @param payerId   付款人身份
     * @return {@link Object}
     */
    @ApiOperation(value = "支付成功后(给自己购买)")
    @GetMapping(value = {"pay/success"})
    @LogAnno
    @SneakyThrows
    public Object success(
                          @NotNull @RequestParam("paymentId") String paymentId,
                          @NotNull @RequestParam("PayerID") String payerId,
                          @RequestParam("subscribeOrderId")Long subscribeOrderId
    ){
        Object obj = wxNewSubscribeService.executePayment(paymentId, payerId);
        log.debug("更新订单信息成功");
        if(!(obj instanceof Payment)){
            return obj;
        }
        Payment payment = (Payment)obj;
        if(payment.getState().equals("approved")){
            log.debug("开始创建订阅用户");
            wxNewSubscribeService.createOrUpdate(subscribeOrderId);
            log.debug("创建订阅用户成功");
            log.info(urlUtils.getBaseURl());
            return ResponseUtil.ok("success");
        }
        return "<script type=\"text/javascript\">location.href=\"/\"</script>" ;
    }


    /**
     * 支付成功后
     *
     * @param userId    用户id
     * @param paymentId 支付id
     * @param payerId   付款人身份
     * @return {@link Object}
     */
    @ApiOperation(value = "支付成功后(赠送)")
    @GetMapping(value = {"payGivee/success"})
    @LogAnno
    @SneakyThrows
    public Object payGiveeSuccess(@LoginUser Integer userId,
                          @NotNull @RequestParam("paymentId") String paymentId,
                          @NotNull @RequestParam("PayerID") String payerId,
                          @RequestParam("subscribeOrderId")Long subscribeOrderId,
                          String message
    ){
        Object obj = wxNewSubscribeService.executePayment(paymentId, payerId);
        log.debug("更新订单信息成功");
        if(!(obj instanceof Payment)){
            return obj;
        }
        Payment payment = (Payment)obj;
        if(payment.getState().equals("approved")){
            log.debug("开始创建订阅用户");
            wxNewSubscribeService.createOrUpdateIsGivee(userId,subscribeOrderId,message);
            log.debug("创建订阅用户成功");
            log.info(urlUtils.getBaseURl());
            return ResponseUtil.ok("success");
        }
        return "<script type=\"text/javascript\">location.href=\"/\"</script>" ;
    }



    /**
     * 取消支付
     *
     * @return {@link Object}
     */
    @PostMapping("pay/cancel")
    @LogAnno
    public Object cancelPay(){
        return ResponseUtil.ok("cancel") ;
    }


    /**
     * 立即订阅
     *
     * @param dto    dto
     * @param userId 用户id
     * @return {@link Object}
     */
    @PostMapping("confirm")
    @LogAnno
    @Transactional
    public Object confirm(@RequestBody SubscribeConfirmDTO dto, @LoginUser Integer userId) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        //前端传递的问题，没有区分余额支付和积分支付。都传递了同样的数值
        if(dto.getPayType().equals(3)){
            dto.setPrice(new BigDecimal(0.00));
        }if(dto.getPayType().equals(1)){
            dto.setPoint(new BigDecimal(0.00));
        }
        dto.setMessage(StrUtil.isNotEmpty(dto.getMessage())?dto.getMessage(): LitemallWXConstants.WX_GIFTCARD_DEFAULT_MESSAGE);
        //创建订阅用户
        LumiereSubscribeUser lumiereSubscribeUser = new LumiereSubscribeUser();
        BeanUtils.copyProperties(dto, lumiereSubscribeUser);
        LitemallUser user = litemallUserService.findById(userId);
        //如果是赠送
        LumiereSubscribeUserLog log = new LumiereSubscribeUserLog();
        if (dto.getGivee() != null) {
            if(RegexUtil.isMobileValid(dto.getGivee()) && dto.getGivee().startsWith(MOBILE_CODE_ONE)){
                dto.setGivee(dto.getGivee().substring(1,dto.getGivee().length()));
            }
            lumiereSubscribeUser.setStatus(Constants.SUBSCRIBE_USER_NOT_ACTIVE);
            log.setBuyType(3);
        } else {
            log.setBuyType(1);
            if (dto.getAutoSub() == 1) {
                lumiereSubscribeUser.setAutoSub(true);
            } else {
                lumiereSubscribeUser.setAutoSub(false);
            }
            lumiereSubscribeUser.setStatus(Constants.SUBSCRIBE_USER_NORMAL);
        }

        if (dto.getAutoSub() != null) {
            if (dto.getAutoSub() == 1) {
                lumiereSubscribeUser.setAutoSub(true);
            } else {
                lumiereSubscribeUser.setAutoSub(false);
            }
        }

        //设置购买者用户id
        lumiereSubscribeUser.setPurchaserId(userId);

        //通过ruleId查询订阅方式
        LumiereSubscribeRule rule = lumiereSubscribeRuleService.queryByPrimaryKey(dto.getRuleId());


        if (rule == null) {
            return ResponseUtil.fail(222, "订阅方式不正确");
        }
        lumiereSubscribeUser.setSubscribeId(rule != null ? rule.getSubscribeId() : null);

        lumiereSubscribeUser.setMethod(rule != null ? rule.getRuleType() : null);
        lumiereSubscribeUser.setRuleId(dto.getRuleId());

        lumiereSubscribeUser.setDeliveryMethod(dto.getTransportType() != null ? dto.getTransportType() : null);
        //计算startTime和endTime
        LocalDateTime startTime = LocalDateTime.now();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar cal = Calendar.getInstance();
        Date startDate = Date.from( startTime.atZone( ZoneId.systemDefault()).toInstant());
        cal.setTime(startDate);
        String end;
        LocalDateTime endTime = null;
        switch (rule.getRuleType()) {
            case 1:
                cal.add(Calendar.DATE, +7);
                end = sdf.format(cal.getTime());
                endTime = LocalDateTime.parse(end, df);
                break;

            case 2:
                cal.add(Calendar.MONTH, +1);
                end = sdf.format(cal.getTime());
                endTime = LocalDateTime.parse(end, df);
                break;

            default:
                cal.add(Calendar.YEAR, +1);
                end = sdf.format(cal.getTime());
                endTime = LocalDateTime.parse(end, df);
                break;
        }

        lumiereSubscribeUser.setStartTime(startTime);
        lumiereSubscribeUser.setEndTime(endTime);

        Object taxPrice = this.getTaxPrice(dto);
        if (taxPrice instanceof ResponseUtil.Response) {
            ResponseUtil.Response resp = (ResponseUtil.Response) taxPrice;
            return ResponseUtil.fail(resp.getErrno(), resp.getErrmsg());
        } else {
            lumiereSubscribeUser.setTaxPrice((BigDecimal) taxPrice);
        }

        if (dto.getDeliveryStartTime() != null) {
            lumiereSubscribeUser.setDeliveryStartTime(LocalTime.parse(dto.getDeliveryStartTime()));
        }

        if (dto.getDeliveryEndTime() != null) {
            lumiereSubscribeUser.setDeliveryEndTime(LocalTime.parse(dto.getDeliveryEndTime()));
        }

        //设置goods_product_id
        lumiereSubscribeUser.setGoodsProductId(queryGoodsProductId(dto.getShopId(), dto.getGoodsId()));

        //插入订阅记录 log表 -- 支付方式

        BeanUtils.copyProperties(dto, log);
        log.setSubscribeId(rule != null ? rule.getSubscribeId() : null);
        log.setAddTime(LocalDateTime.now());
        log.setBuyTime(LocalDateTime.now());
        log.setExpireTime(endTime);
        log.setUserName(user.getUsername());

        //扣款
        if(dto.getPrice() != null){
            dto.setPrice(dto.getPrice().multiply(new BigDecimal(dto.getNumber())));
        }

        if(dto.getPoint() != null){
            dto.setPoint(dto.getPoint().multiply(new BigDecimal(dto.getNumber())));
        }

        LitemallUser u = litemallUserService.findById(userId);
        LumiereSubscribe subscribe = lumiereSubscribeService.findById(lumiereSubscribeUser.getSubscribeId());
        //判断订阅是否状态正常
        if(subscribe.getStatus()!=1){
            return ResponseUtil.fail(SUBSCRIBE_STATUS_SOLD_OUT, "改订阅已下架，请去订购其它服务");
        }
        log.setSubscribeName(subscribe.getName());
        if (dto.getPrice() != null && dto.getPayType() != 3) {
            if (dto.getPayType() == 2) {   //礼物卡
                LitemallGiftCardUser cardUser = litemallGiftCardUserService.findById(dto.getGiftCardUserId());
                if (cardUser.getAmount().compareTo(dto.getPrice() != null ? dto.getPrice() : rule.getPrice()) != -1) {
                    cardUser.setAmount(cardUser.getAmount().subtract(dto.getPrice() != null ? dto.getPrice() : rule.getPrice()));

                    litemallGiftCardUserService.updateById(cardUser);
                    saveGiftLog(null, cardUser, userId, "购买订阅",dto.getPrice() != null ? dto.getPrice() : rule.getPrice());
                } else {
                    return ResponseUtil.fail(CARD_AVALIABLE_AMOUNT_NOT_ENOUGH, "礼物卡余额不足");
                }
            } else {                       //余额
                //扣减余额

                if (u.getAvailableAmount().compareTo(dto.getPrice() != null ? dto.getPrice() : rule.getPrice()) != -1) {
                    u.setAvailableAmount(u.getAvailableAmount().subtract(dto.getPrice() != null ? dto.getPrice() : rule.getPrice()));
                    litemallUserService.updateById(u);

                    saveLog(dto.getPrice() != null ? dto.getPrice() : rule.getPrice(), user,
                            log.getBuyType() != 3 ? LOG_GIFTCARD_SUBSCRIBE_CONSUME : LOG_GIFTCARD_SUBSCRIBE_GIVE
                            ,rule.getSubscribeId(),u);
                } else {
                    return ResponseUtil.fail(NOT_ENOUGH_AMOUNT);
                }

            }
            lumiereSubscribeUser.setPrice(dto.getPrice() != null ? dto.getPrice() : rule.getPrice());
            log.setPrice((dto.getPrice() != null ? dto.getPrice() : rule.getPrice()).multiply(new BigDecimal(dto.getNumber())));
        } else {
            if (dto.getPoint() == null) {
                return ResponseUtil.fail(444, "支付积分不能为空");
            } else {
                //扣减积分
                if (u.getPoints().compareTo(dto.getPoint()) != -1) {
                    u.setPoints(u.getPoints().subtract(dto.getPoint()));
                    litemallUserService.updateById(u);

                    LitemallIntegralLog l = new LitemallIntegralLog();
                    l.setUserId(userId);
                    l.setType(Constants.INTEGRAL_LOG_TYPE_CONSUMPTION);
                    l.setPoints(user.getPoints());
                    l.setChangePoints(dto.getPoint().multiply(new BigDecimal(-1)));
                    //添加详细信息
                    l.setUseType(3);
                    l.setSubscribeName(subscribe.getName());
                    integralLogService.add(l);
                } else {
                    return ResponseUtil.fail(POINT_NOT_ENOUGH, "积分不足");
                }

                lumiereSubscribeUser.setPoint(dto.getPoint().intValue());
                log.setPoint(Integer.parseInt(dto.getPoint().toString()));
            }
        }

        if (dto.getGivee() != null) {
            log.setStatus(3);
        } else {
            log.setStatus(1);
        }
        lumiereSubscribeUser.setShopId(dto.getShopId());
        if (StrUtil.isNotBlank(dto.getGivee())?ObjectUtil.isNotEmpty(litemallUserService.queryMobileOrEmail(dto.getGivee())):false) {
            LitemallUser giveeUser = litemallUserService.queryMobileOrEmail(dto.getGivee());
            //插入user表和log表
            lumiereSubscribeUser.setUserName(giveeUser.getUsername());
            lumiereSubscribeUser.setUserId(giveeUser.getId());
            lumiereSubscribeUser.setAddTime(LocalDateTime.now());
            lumiereSubscribeUser.setUpdateTime(LocalDateTime.now());
            lumiereSubscribeUserService.add(lumiereSubscribeUser);

            log.setUserId(userId);
            log.setUserName(giveeUser.getUsername());
            log.setSubscribeUserId(lumiereSubscribeUser.getId());
            lumiereSubscribeUserLogService.add(log);
            //发送通知
            wxNewSubscribeManageService.sendNotificationToExistUser(dto,user,giveeUser,lumiereSubscribeUser);
            return ResponseUtil.ok("success");
        }else if(StrUtil.isNotBlank(dto.getGivee())?ObjectUtil.isEmpty(litemallUserService.queryMobileOrEmail(dto.getGivee())):false){
            //订阅用户表
            lumiereSubscribeUser.setUserName(dto.getGivee());
            lumiereSubscribeUser.setAddTime(LocalDateTime.now());
            lumiereSubscribeUser.setUpdateTime(LocalDateTime.now());
            lumiereSubscribeUserService.add(lumiereSubscribeUser);

            log.setUserId(userId);
            log.setUserName(dto.getGivee());
            log.setSubscribeUserId(lumiereSubscribeUser.getId());
            lumiereSubscribeUserLogService.add(log);
            //发送通知
            wxNewSubscribeManageService.sendNotificationToNotExistUser(dto,user,lumiereSubscribeUser);
            return ResponseUtil.ok("success");
        }else{
            //插入user表和log表
            lumiereSubscribeUser.setUserId(userId);
            lumiereSubscribeUser.setUserName(user.getUsername());
            lumiereSubscribeUser.setAddTime(LocalDateTime.now());
            lumiereSubscribeUser.setUpdateTime(LocalDateTime.now());
            lumiereSubscribeUserService.add(lumiereSubscribeUser);

            log.setUserId(userId);
            log.setUserName(user.getUsername());
            log.setSubscribeUserId(lumiereSubscribeUser.getId());
            int add = lumiereSubscribeUserLogService.add(log);

            if (add==0){return ResponseUtil.fail("订阅失败！");}
            //给自己购买
            awsNotifyService.sendSms(MOBILE_CODE_ONE+user.getMobile(), "Congratulations, you got the "+subscribe.getName(),Constants.AWS_MESSAGE_TYPE_TRANSACTIONAL);
            noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER,"Subscribe purchase", "Subscribe purchase succeeded", userId, lumiereSubscribeUser);

            return ResponseUtil.ok("订阅成功");
        }


    }


    /**
     * 列表
     * 查询当前门店可发布的订阅
     *
     * @param userId 用户id
     * @param page   页面
     * @param shopId 商店id
     * @param limit  限制
     * @param sort   排序
     * @param order  订单
     * @return {@link Object}
     */
    @GetMapping("list")
    @LogAnno
    public Object list(@LoginUser Integer userId, @RequestParam(defaultValue = "1") Integer page, Integer shopId,
                       @RequestParam(defaultValue = "20") Integer limit,
                       @Sort @RequestParam(defaultValue = "add_time") String sort,
                       @Order @RequestParam(defaultValue = "desc") String order) {

        if (userId == null) {
            return ResponseUtil.unlogin();
        }

        //通过shopId查询适配的订阅设置
        IPage<LumiereSubscribe> lumiereSubscribeList = lumiereSubscribeService.queryAll(page, limit, sort, order,null);

        //查询门店的cityId
        Integer cityId = getShopRegionId(shopId);
        if(shopId != null){
            List<LumiereSubscribe> lumiereSubscribeFilterList = new ArrayList<>();
            lumiereSubscribeFilterList = lumiereSubscribeList.getRecords().stream().filter(subscribe -> {

                if(subscribe.getRegionIds() != null){
                    for (int i = 0; i < subscribe.getRegionIds().length; i++) {
                        if (subscribe.getRegionIds()[i].equals(cityId)) {
                            return true;
                        }
                    }
                    return false;
                }else{
                    return true;
                }
            }).collect(Collectors.toList());
            lumiereSubscribeList.setRecords(lumiereSubscribeFilterList);
        }

        List<SubscribeListVo> vos = lumiereSubscribeList.getRecords().stream().map(vo -> {
            SubscribeListVo v = new SubscribeListVo();
            BeanUtils.copyProperties(vo, v);
            return v;
        }).filter(s -> {
            if (s.getStatus() == 1 && (s.getUseRange() == 3 || s.getUseRange() == 1)) {
                return true;
            } else {
                return false;
            }
        }).collect(Collectors.toList());


        vos = vos.stream().map(subscribe -> {
            List<LumiereSubscribeUser> users = lumiereSubscribeUserService.queryByUserIdAndSubscribeId(userId, subscribe.getId());
            if (users.size() > 0) {

                LumiereSubscribeUser user = users.stream().max(Comparator.comparing((LumiereSubscribeUser::getId))).get();
                subscribe.setSubscribeUserId(user.getId());
                subscribe.setShopId(user.getShopId());
            }

            subscribe.setStatus(0);
            //查询价格和积分，以及配置
            List<LumiereSubscribeRule> rules = lumiereSubscribeRuleService.querySubscribeRule(subscribe.getId());

            rules = rules.stream().filter(rul -> {
                if(( rul.getPrice() == null || rul.getPrice().compareTo(BigDecimal.ZERO) == 0) && (rul.getPoint() == null || rul.getPoint() - 0 == 0) ){
                    return false;
                }else{
                    return true;
                }
            }).collect(Collectors.toList());

            LumiereSubscribeRule rule = null;
            if(rules.size() == 0){
                return null;
            }else{
                rule = rules.stream().min(Comparator.comparing((LumiereSubscribeRule::getId))).get();
            }

            subscribe.setPrice(rule.getPrice());
            //subscribe.setPoint(new BigDecimal(rule.getPoint()));
            if(rule.getPoint() != null){
                subscribe.setPoint(new BigDecimal(rule.getPoint()));
            }

            subscribe.setNextSubPrice(rule.getNextSubPrice());
            if(rule.getNextSubPoint() != null){
                subscribe.setNextSubPoint(new BigDecimal(rule.getNextSubPoint()));
            }

            if (rule.getDaysTimes() != null && rule.getDaysTimes() != 0) {
                subscribe.setType("天");
                subscribe.setFrequency(rule.getDaysTimes());
            } else if (rule.getWeekTimes() != null && rule.getWeekTimes() != 0) {
                subscribe.setType("周");
                subscribe.setFrequency(rule.getWeekTimes());
            } else if (rule.getMonthTimes() != null && rule.getMonthTimes() != 0) {
                subscribe.setType("月");
                subscribe.setFrequency(rule.getMonthTimes());
            } else if (rule.getYearTimes() != null && rule.getYearTimes() != 0) {
                subscribe.setType("年");
                subscribe.setFrequency(rule.getYearTimes());
            }

            if(subscribe.getPrice()!= null){
                subscribe.setPrice(subscribe.getPrice().setScale(2));
            }

            if(subscribe.getNextSubPrice()!= null){
                subscribe.setNextSubPrice(subscribe.getNextSubPrice().setScale(2));
            }



            return subscribe;
        }).collect(Collectors.toList());

        vos = vos.stream().filter(v -> {
            if(v == null){
                return false;
            }else {
                return true;
            }
        }).collect(Collectors.toList());


        Pageable pageable = PageRequest.of(page - 1,limit);
        return ResponseUtil.ok(PageUtil.getPageLumierePayMemberUserLogVo(pageable,vos));
    }


    /**
     * 查询订阅详情
     *
     * @param userId          用户id
     * @param subscribeUserId 订阅用户id
     * @param subscribeId     订阅id
     * @return {@link Object}
     */
    @GetMapping("/detail")
    @LogAnno
    public Object detail(@LoginUser Integer userId, Integer subscribeUserId, Integer subscribeId) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        LumiereSubscribeUser subscribeUser = null;
        if (subscribeUserId != null) {
            subscribeUser = lumiereSubscribeUserService.findById(subscribeUserId);
            subscribeId = subscribeUser.getSubscribeId();
        }
        //查询可订阅的商品
        List<LumiereSubscribeGoods> goods = lumiereSubscirbeGoodsService.querySubscribeGoodsById(subscribeId);
        //查询订阅相关的配送方式(年,月,周,日)
        List<LumiereSubscribeRule> rules = lumiereSubscribeRuleService.querySubscribeRule(subscribeId);
        LumiereSubscribeUser finalSubscribeUser = subscribeUser;
        List<LumiereSubscribeGoodsDTO> goodDtos = goods.stream().map(good -> {
            LumiereSubscribeGoodsDTO dto = new LumiereSubscribeGoodsDTO();
            BeanUtils.copyProperties(good, dto);
            if(finalSubscribeUser != null){
                if(good.getGoodsId().equals(finalSubscribeUser.getGoodsId())){
                    dto.setIsSelected(true);
                }else{
                    dto.setIsSelected(false);
                }
            }else{
                dto.setIsSelected(false);
            }
            //根据规格Id查询name
            String[] names = new String[good.getSpecificationIds().length];
            List<LitemallGoodsSpecification> specifications = litemallGoodsSpecificationService.queryByIds(good.getSpecificationIds());
            for (int i = 0; i < specifications.size(); i++) {
                names[i] = specifications.get(i).getSpecification();
            }
            //查询门店在哪个地区
            Integer value = goodsTaxService.findGoodsTax(good.getGoodsId());
            dto.setTax(value);
            dto.setSpecificationNames(names);
            dto.setNumber(good.getNumber());
            String goodsName = litemallGoodsService.findById(good.getGoodsId()).getName();
            dto.setGoodsName(goodsName);
            return dto;
        }).collect(Collectors.toList());

        SubscribeDTO dto = new SubscribeDTO();
        dto.setGoods(goodDtos);
        //由订阅或者续订决定数据中的订阅方式
        if(subscribeUserId != null){
            List<LumiereSubscribeRule> rs = new ArrayList<>();
            for (int i = 0; i < rules.size(); i++) {
                if(subscribeUser.getRuleId().equals(rules.get(i).getId())){
                    rs.add(rules.get(i));
                }
            }
            dto.setRules(rs);
        }else{
            dto.setRules(rules);
        }

        //查询订阅图片
        LumiereSubscribe lumiereSubscribe = lumiereSubscribeService.findById(subscribeId);
        dto.setStatus(lumiereSubscribe.getStatus());
        dto.setTimeRanges(lumiereSubscribe.getTimeRanges());
        dto.setPicture(lumiereSubscribe.getPicture());
        if (lumiereSubscribe.getAutoSub() == true) {
            dto.setAutoSub(1);
        } else {
            dto.setAutoSub(0);
        }
        dto.setTransportType(lumiereSubscribe.getTransportType());
        if (subscribeUserId != null) {
            dto.setExpiredDate(subscribeUser.getEndTime().toLocalDate().toString());
        }
        if (subscribeUserId == null) {
            List<LumiereSubscribeRule> rs = dto.getRules();
            for (int i = 0; i < rs.size(); i++) {
                rs.get(i).setNextSubPrice(null);
                rs.get(i).setNextSubPoint(null);
            }
        }
        dto.setOrderRule(lumiereSubscribe.getOrderRule());
        dto.setNumber(ObjectUtil.isNotNull(finalSubscribeUser)&&finalSubscribeUser.getNumber()!=null?finalSubscribeUser.getNumber():1);
        dto.setDesc(lumiereSubscribe.getDesc() != null ? lumiereSubscribe.getDesc() : "");
        return ResponseUtil.ok(dto);
    }

    /**
     * 支付方法
     * 查询可用的支付方式(积分,余额，礼物卡)
     *
     * @param userId 用户id
     * @return {@link Object}
     */
    @GetMapping("payMethod")
    @LogAnno
    public Object payMethod(@LoginUser Integer userId) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        //查询积分
        //查询余额
        LitemallUser litemallUser = litemallUserService.findById(userId);
        BigDecimal availableAmount = litemallUser.getAvailableAmount();
        BigDecimal points = litemallUser.getPoints();

        //查询礼物卡lumiereLevelMemberPointService
        List<LitemallGiftCardUser> cards = litemallGiftCardUserService.queryByUserId(userId);

        PayMethodDTO dto = new PayMethodDTO();
        dto.setPoints(points);
        dto.setAvailableAmount(availableAmount);
        dto.setCards(cards);

        return ResponseUtil.ok(dto);
    }

    /**
     * 邮件地址
     * 查询用户的邮寄收货地址
     *
     * @param userId 用户id
     * @return {@link Object}
     */
    @GetMapping("mailAddress")
    @LogAnno
    public Object mailAddress(@LoginUser Integer userId) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        List<LitemallAddress> addresses = litemallAddressService.findByUserId(userId);
        return ResponseUtil.okList(addresses);
    }

    /**
     * 店地址
     * 查询所有的shop门店
     *
     * @param goodsId   商品id
     * @param longitude 经度
     * @param latitude  纬度
     * @param type      类型
     * @return {@link Object}
     */
    @GetMapping("shopAddress")
    @LogAnno
    public Object shopAddress(@RequestParam Integer goodsId, BigDecimal longitude, BigDecimal latitude, Integer type,Integer page,Integer limit) {
        return wxShopService.queryGoodsShop(goodsId, longitude, latitude, type,page,limit);
    }

    /**
     * 得到距离
     *
     * @param lat1 lat1
     * @param lng1 lng1
     * @param lat2 lat2
     * @param lng2 lng2
     * @return {@link Object}
     *///计算选择配送门店到收货地址的距离
    @GetMapping("getDistance")
    @LogAnno
    public Object getDistance(@RequestParam double lat1, @RequestParam double lng1,
                              @RequestParam double lat2, @RequestParam double lng2) {
        Double distance = LocationUtils.getDistance(lat1, lng1, lat2, lng2);
        return ResponseUtil.ok(distance);
    }


    /**
     *
     * @param subscribeUserId 订阅用户id
     * @return {@link Object}
     */
    @GetMapping("reDetail")
    @LogAnno
    @Transactional
    public Object reDetail(@RequestParam Integer subscribeUserId) {
        LumiereSubscribeUser user = lumiereSubscribeUserService.findById(subscribeUserId);


        /**
         * 查询用户订阅信息
         */
        SubscribeUserVo subscribeUserVo = new SubscribeUserVo();
        //查询规格，大杯
        LumiereSubscribeGoods goodsSpecification = lumiereSubscirbeGoodsService.findByGoodsIdAndSubId(user.getGoodsId(), user.getSubscribeId());
        LumiereSubscribeGoodsDTO lumiereSubscribeGoodsDto = new LumiereSubscribeGoodsDTO();

        //根据规格Id查询name
        String[] names = new String[goodsSpecification.getSpecificationIds().length];
        List<LitemallGoodsSpecification> specifications = litemallGoodsSpecificationService.queryByIds(goodsSpecification.getSpecificationIds());
        for (int i = 0; i < specifications.size(); i++) {
            names[i] = specifications.get(i).getSpecification();
        }

        //查询门店在哪个地区
        Integer value = goodsTaxService.findGoodsTax(goodsSpecification.getGoodsId());
        lumiereSubscribeGoodsDto.setGoodsId(user.getGoodsId());
        lumiereSubscribeGoodsDto.setTax(value);

        lumiereSubscribeGoodsDto.setSpecificationNames(names);

        String goodsName = litemallGoodsService.findById(goodsSpecification.getGoodsId()).getName();
        lumiereSubscribeGoodsDto.setGoodsName(goodsName);

        //订阅用户对应的商品信息
        subscribeUserVo.setLumiereSubscribeGoodsDto(lumiereSubscribeGoodsDto);


        //查询门店信息
        LitemallShop shop = litemallShopService.findById(user.getShopId());
        subscribeUserVo.setLitemallShop(shop);

        //查询rule信息
        LumiereSubscribeRule rule = lumiereSubscribeRuleService.queryByPrimaryKey(user.getRuleId());
        subscribeUserVo.setLumiereSubscribeRule(rule);
        BeanUtils.copyProperties(user, subscribeUserVo);
        subscribeUserVo.setSubscribeUserId(user.getId());

        //配送地址
        LitemallAddress litemallAddress = litemallAddressService.findById(user.getAddressId());
        subscribeUserVo.setLitemallAddress(litemallAddress);

        return ResponseUtil.ok(subscribeUserVo);
    }


    /**
     * 活跃
     * 激活
     *
     * @param subscribeUserId   订阅用户id
     * @param deliveryStartTime 交付开始时间
     * @param deliveryEndTime   交付结束时间
     * @param deliveryMethod    交货方法
     * @param goodsId           商品id
     * @param goodsProductId    货物产品id
     * @param number            数量
     * @param deliveryDays      交货日
     * @param deliveryDates     交付日期
     * @return {@link Object}
     */
    @PostMapping("active")
    @LogAnno
    @Transactional
    public Object active(Integer subscribeUserId, String deliveryStartTime,
                         String deliveryEndTime, Byte deliveryMethod,
                         Integer goodsId, Integer goodsProductId,
                         Integer number, Integer[] deliveryDays, String[] deliveryDates,Integer shopId) {
        //修改user状态
        LumiereSubscribeUser user = lumiereSubscribeUserService.findById(subscribeUserId);
        LocalTime startT = LocalTime.parse(deliveryStartTime);
        LocalTime endT = LocalTime.parse(deliveryEndTime);
        user.setId(subscribeUserId);
        user.setDeliveryStartTime(startT);
        user.setDeliveryEndTime(endT);
        user.setDeliveryMethod(deliveryMethod);
        user.setGoodsId(goodsId);
        user.setGoodsProductId(goodsProductId);
        user.setNumber(number);
        user.setDeliveryDays(deliveryDays);
        user.setDeliveryDates(deliveryDates);
        user.setStatus(1);
        user.setShopId(shopId);
        lumiereSubscribeUserService.update(user);
        return ResponseUtil.ok("激活成功");
    }

    /**
     * reneval
     * 续订
     *
     * @param dto dto
     * @return {@link Object}
     */
    @PostMapping("reneval")
    @LogAnno
    @Transactional
    public Object reneval(@RequestBody SubscribeConfirmDTO dto) {

        if (dto.getSubscribeUserId() == null) {
            return ResponseUtil.fail("被修改的subscribeUserId不能为空");
        }

        //判断该订阅是否已经过期
        LumiereSubscribeUser oldUser = lumiereSubscribeUserService.findById(dto.getSubscribeUserId());
        if(oldUser.getEndTime() != null){
            if(LocalDate.now().isAfter(oldUser.getEndTime().toLocalDate())){
                return ResponseUtil.fail(SUBSCRIBE_EXPIRED,"订阅过期");
            }
        }
        //判断是否已下架 停用
        LumiereSubscribe lumiereSubscribe = lumiereSubscribeService.findById(oldUser.getSubscribeId());
        if(lumiereSubscribe.getStatus()==0){
            return ResponseUtil.fail(SUBSCRIBE_DISCONTINUED,"订阅停用,请去订阅新的服务");
        }

        //产生一条新log记录
        LumiereSubscribeRule rule = lumiereSubscribeRuleService.queryByPrimaryKey(dto.getRuleId());
        dto.setPrice(rule.getNextSubPrice());
        dto.setPoint(new BigDecimal(rule.getNextSubPoint()));
        LumiereSubscribeUserLog log = new LumiereSubscribeUserLog();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String end;
        LocalDateTime endTime;
        Calendar cal = Calendar.getInstance();

        BeanUtils.copyProperties(dto, log);

        log.setSubscribeId(rule != null ? rule.getSubscribeId() : null);
        log.setAddTime(LocalDateTime.now());
        log.setBuyType(2);

        cal.setTime(new Date());
        log.setBuyTime(LocalDateTime.now());
        log.setStatus(1);
        log.setAddTime(LocalDateTime.now());

        //插入一条数据到user中，但是link_id
        LumiereSubscribeUser user = new LumiereSubscribeUser();
        BeanUtils.copyProperties(dto, user);
        user.setLinkId(dto.getSubscribeUserId());
        user.setSubscribeId(rule != null ? rule.getSubscribeId() : null);
        user.setMethod(rule != null ? rule.getRuleType() : null);
        user.setDeliveryMethod(dto.getTransportType() != null ? dto.getTransportType() : null);
        user.setStatus(1);
        user.setRuleId(dto.getRuleId());
        if (dto.getAutoSub() != null) {
            if (dto.getAutoSub() == 1) {
                user.setAutoSub(true);
            } else {
                user.setAutoSub(false);
            }
        }

        Integer productId = queryGoodsProductId(dto.getShopId(), dto.getGoodsId());
        if (productId == null) {
            return ResponseUtil.fail(GOODS_NO_STOCK, "门店没有该商品");
        }
        user.setGoodsProductId(productId);

        //处理订阅方式相关
        endTime = oldUser.getEndTime();
        ZonedDateTime zonedDateTime = endTime.atZone(ZoneId.systemDefault());
        Date d = Date.from(zonedDateTime.toInstant());
        cal.setTime(d);
        user.setDeliveryStartTime(LocalTime.parse(dto.getDeliveryStartTime()));
        user.setDeliveryEndTime(LocalTime.parse(dto.getDeliveryEndTime()));
        user.setStartTime(endTime);
        user.setUserId(oldUser.getUserId());
        user.setShopId(oldUser.getShopId());
        switch (rule.getRuleType()) {
            case 1:
                cal.add(Calendar.DATE, +7);
                end = sdf.format(cal.getTime());
                break;

            case 2:
                cal.add(Calendar.MONTH, +1);
                end = sdf.format(cal.getTime());
                break;

            default:
                cal.add(Calendar.YEAR, +1);
                end = sdf.format(cal.getTime());
                break;
        }
        log.setExpireTime(LocalDateTime.parse(end, df));
        user.setEndTime(LocalDateTime.parse(end, df));

        //设置税费相关
        if (dto.getPrice() == null && dto.getPrice() == null) {
            List<LumiereSubscribeUserLog> ls = lumiereSubscribeUserLogService.findByUserId(dto.getSubscribeUserId());
            LumiereSubscribeUserLog l = ls.stream().max(Comparator.comparing((LumiereSubscribeUserLog::getId))).get();
            dto.setPayType(l.getPayType());
            if (l.getPrice() != null) {
                dto.setPrice(l.getPrice());
            } else {
                dto.setPoint(BigDecimal.valueOf(l.getPoint()));
            }
        }

        //扣款
        LitemallUser u = litemallUserService.findById(user.getUserId());
        BigDecimal reducePrice = dto.getPrice().multiply(new BigDecimal(dto.getNumber()));
        if (dto.getPrice() != null && dto.getPayType() != 3) {
            if (dto.getPayType() == 2) {   //礼物卡
                LitemallGiftCardUser cardUser = litemallGiftCardUserService.findById(dto.getGiftCardUserId());
                if (cardUser.getAmount().compareTo(reducePrice) != -1) {
                    cardUser.setAmount(cardUser.getAmount().subtract(reducePrice));

                    litemallGiftCardUserService.updateById(cardUser);
                    saveGiftLog(null, cardUser, u.getId(), "续费订阅",reducePrice);
//                    saveLog(dto.getPrice(),u,(byte)2);
                } else {
                    return ResponseUtil.fail(CARD_AVALIABLE_AMOUNT_NOT_ENOUGH, "礼物卡余额不足");
                }
            } else {                       //余额
                //扣减余额
                if (u.getAvailableAmount().compareTo(reducePrice) != -1) {
                    u.setAvailableAmount(u.getAvailableAmount().subtract(reducePrice));
                    litemallUserService.updateById(u);

                    saveLog(dto.getPrice(), u, LOG_GIFTCARD_SUBSCRIBE_RENEVAL,rule.getSubscribeId(),u);
                } else {
                    return ResponseUtil.fail(NOT_ENOUGH_AMOUNT);
                }
            }
            user.setPrice(dto.getPrice());
            log.setPrice(dto.getPrice().multiply(new BigDecimal(dto.getNumber())));
        } else {
            if (dto.getPoint() != null) {
                BigDecimal reducePoint = dto.getPoint().multiply(new BigDecimal(dto.getNumber()));
                //扣减积分
                if (u.getPoints().compareTo(reducePoint) != -1) {
                    u.setPoints(u.getPoints().subtract(reducePoint));
                    litemallUserService.updateById(u);

                    LitemallIntegralLog l = new LitemallIntegralLog();
                    l.setUserId(u.getId());
                    l.setType(Constants.INTEGRAL_LOG_TYPE_MINUS);
                    l.setPoints(u.getPoints());
                    l.setChangePoints(dto.getPoint().multiply(new BigDecimal(-1)));
                    integralLogService.add(l);
                } else {
                    return ResponseUtil.fail(POINT_NOT_ENOUGH, "积分不足");
                }

                user.setPoint(dto.getPoint().intValue());
                log.setPoint(Integer.parseInt(dto.getPoint().toString()));
            } else {
                return ResponseUtil.fail(555, "支付积分不能为空");
            }
        }

        //税费相关
        Object taxPrice = this.getTaxPrice(dto);
        if (taxPrice instanceof ResponseUtil.Response) {
            ResponseUtil.Response resp = (ResponseUtil.Response) taxPrice;
            return ResponseUtil.fail(resp.getErrno(), resp.getErrmsg());
        } else {
            user.setTaxPrice((BigDecimal) taxPrice);
        }

        user.setPurchaserId(user.getUserId());
//        user.setId(dto.getSubscribeUserId());
        user.setAddTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        lumiereSubscribeUserService.add(user);
        log.setUserId(user.getUserId());
        log.setSubscribeUserId(user.getId());
        log.setUserName(u.getUsername());
        log.setSubscribeUserId(dto.getSubscribeUserId());
        lumiereSubscribeUserLogService.add(log);

        LumiereSubscribe subscribe = lumiereSubscribeService.findById(user.getSubscribeId());

        awsNotifyService.sendSms(MOBILE_CODE_ONE+u.getMobile(), "Congratulations, you got the "+subscribe.getName(), Constants.AWS_MESSAGE_TYPE_TRANSACTIONAL);

        noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER,"Subscribe reneval", "Subscribe reneval succeeded", user.getUserId(), user);
        //
        return ResponseUtil.ok("续订成功");
    }


    /**
     * 我清单
     * 获取用户所有的lumiere_subscribe_user_order表中的数据
     *
     * @param userId 用户id
     * @param page   页面
     * @param limit  限制
     * @param sort   排序
     * @param order  订单
     * @return {@link Object}
     */
    @GetMapping("myList")
    @LogAnno
    public Object myList(@LoginUser Integer userId,
                         @RequestParam(defaultValue = "1") Integer page,
                         @RequestParam(defaultValue = "10000") Integer limit,
                         @Sort @RequestParam(defaultValue = "add_time") String sort,
                         @Order @RequestParam(defaultValue = "desc") String order) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        List<Integer> statusList = new ArrayList<>();
        statusList.add(1);
        statusList.add(2);
        List<LumiereSubscribeUser> users = lumiereSubscribeUserService.queryByUserId(userId, page, limit, sort, "desc", statusList);

        List<LumiereSubscribeUser> userList = new ArrayList<>();
        for (int i = 0; i < users.size(); i++) {
            LumiereSubscribeUser subscribeUser = getExpiredSubscribeUser(users, users.get(i).getId(),users.get(i).getStartTime());
            if( subscribeUser.getEndTime() == null || subscribeUser.getEndTime().toLocalDate().isAfter(LocalDate.now())){
                userList.add(subscribeUser);
            }
        }

        List<Integer> giveStatusList = new ArrayList<>();
        giveStatusList.add(3);
        giveStatusList.add(4);
        List<LumiereSubscribeUser> giveUsers = lumiereSubscribeUserService.queryByUserId(userId, page, limit, sort, order, giveStatusList);

        for (int i = 0; i < giveUsers.size(); i++) {
            LumiereSubscribeUser subscribeUser = getExpiredSubscribeUser(giveUsers, giveUsers.get(i).getId(),giveUsers.get(i).getStartTime());
            if( subscribeUser.getEndTime() == null || subscribeUser.getEndTime().toLocalDate().isAfter(LocalDate.now())){
                userList.add(subscribeUser);
            }
        }

        List<SubscribeUserListVo> vos = userList.stream().map(user -> {

            LumiereSubscribe subscribe = lumiereSubscribeService.findById(user.getSubscribeId());
            SubscribeUserListVo vo = new SubscribeUserListVo();
            //查询订阅图片
            vo.setPicture(subscribe.getPicture());
            BeanUtils.copyProperties(user, vo);
            vo.setSubscribeUserId(user.getId());
            vo.setSubscribeName(subscribe.getName());

            if (user.getRuleId() != null) {
                LumiereSubscribeRule rule = lumiereSubscribeRuleService.findById(user.getRuleId());
                vo.setRenevalPrice(rule.getNextSubPrice());
                vo.setRenevalPoint(rule.getNextSubPoint()!=null?new BigDecimal(rule.getNextSubPoint()):null);
            }

            if(vo.getPrice()!= null){
                vo.setPrice(vo.getPrice().setScale(2));
            }

            if(vo.getRenevalPrice()!= null){
                vo.setRenevalPrice(vo.getRenevalPrice().setScale(2));
            }
            return vo;
        }).collect(Collectors.toList());

        vos = vos.stream().sorted(Comparator.comparing(SubscribeUserListVo::getEndTime,Comparator.nullsLast(LocalDateTime::compareTo)).reversed()).collect(Collectors.toList());
        return ResponseUtil.okList(vos);
    }

    /**
     * 我订单列表
     * 获取订单列表
     *
     * @param userId 用户id
     * @param page   页面
     * @param limit  限制
     * @param sort   排序
     * @param order  订单
     * @return {@link Object}
     */
    @GetMapping("myOrderList")
    @LogAnno
    public Object myOrderList(@LoginUser Integer userId,
                              @RequestParam(defaultValue = "1") Integer page,
                              @RequestParam(defaultValue = "10") Integer limit,
                              @Sort @RequestParam(defaultValue = "add_time") String sort,
                              @Order @RequestParam(defaultValue = "desc") String order) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }

        /*List<org.linlinjava.litemall.db.dto.SubscribeUserOrderDTO> subscribeUserOrderDTOS = lumiereSubscribeUserService.myOrderList(page, limit, userId).stream()
                .filter(subscribeUserOrderDTO->subscribeUserOrderDTO.getReceiptTime()!=null)
                .map(subscribeUserOrderDTO -> {
                    Integer specificationId = lumiereSubscirbeGoodsService.list(Wrappers.lambdaQuery(LumiereSubscribeGoods.class)
                            .eq(LumiereSubscribeGoods::getSubscribeId, subscribeUserOrderDTO.getSubscribeId())
                    ).get(0).getSpecificationIds()[0];
                    subscribeUserOrderDTO.setSpecifications(litemallGoodsSpecificationService.findById(specificationId).getSpecification());
                    subscribeUserOrderDTO.setAddress(ObjectUtil.isNotNull(subscribeUserOrderDTO.getAddressId())?litemallAddressService.findById(subscribeUserOrderDTO.getAddressId()).getAddressDetail():null);
                    return subscribeUserOrderDTO;
                })
                .sorted(Comparator.comparing(org.linlinjava.litemall.db.dto.SubscribeUserOrderDTO::getStatus).
                    thenComparing(org.linlinjava.litemall.db.dto.SubscribeUserOrderDTO::getReceiptTime).thenComparing(org.linlinjava.litemall.db.dto.SubscribeUserOrderDTO::getDeliveryStartTime).reversed())
                .collect(Collectors.toList());*/

        /*List<SubscribeUserOrderDTO> subscribeUserOrderDTOList = lumiereSubscribeUserService.selectJoinList(SubscribeUserOrderDTO.class, new MPJLambdaWrapper<LumiereSubscribeUser>()
                .selectAll(LumiereSubscribeUser.class)
                .selectAs(LumiereSubscribeUserOrder::getOrderId,SubscribeUserOrderDTO::getUserOrderId)
                .selectAs(LitemallGoods::getName,SubscribeUserOrderDTO::getGoodsName)
                .selectAs(LumiereSubscribe::getId,SubscribeUserOrderDTO::getSubscribeId)
                .selectAs(LitemallGoods::getShopName,SubscribeUserOrderDTO::getShopName)
                .selectAs(LumiereSubscribe::getName,SubscribeUserOrderDTO::getSubscribeName)
                .selectAs(LumiereSubscribeUser::getMethod,SubscribeUserOrderDTO::getTransportType)
                .selectAs(LumiereSubscribeUserOrder::getReceiptTime,SubscribeUserOrderDTO::getReceiptTime)
                .selectAs(LumiereSubscribeUser::getAddressId,SubscribeUserOrderDTO::getAddressId)
                .selectAs(LumiereSubscribeUserOrder::getStatus,SubscribeUserOrderDTO::getStatus)
                .selectAs(LitemallAddress::getAddressDetail,SubscribeUserOrderDTO::getAddress)
                .leftJoin(LumiereSubscribeUserOrder.class, LumiereSubscribeUserOrder::getSubscribeUserId, LumiereSubscribeUser::getId)
                .leftJoin(LumiereSubscribe.class, LumiereSubscribe::getId, LumiereSubscribeUser::getSubscribeId)
                .leftJoin(LitemallGoods.class, LitemallGoods::getId, LumiereSubscribeUser::getGoodsId)
                .leftJoin(LitemallAddress.class, LitemallAddress::getId, LumiereSubscribeUser::getAddressId)
                .eq(LumiereSubscribeUser::getUserId, userId)
                .eq(LumiereSubscribeUser::getDeleted, 0)
                .orderByDesc(LumiereSubscribeUserOrder::getAddTime)
        );


        subscribeUserOrderDTOList=subscribeUserOrderDTOList.stream().map(subscribeUserOrderDTO -> {
            Integer specificationId = lumiereSubscirbeGoodsService.list(Wrappers.lambdaQuery(LumiereSubscribeGoods.class)
                    .eq(LumiereSubscribeGoods::getSubscribeId, subscribeUserOrderDTO.getSubscribeId())
            ).get(0).getSpecificationIds()[0];
            subscribeUserOrderDTO.setSpecifications(litemallGoodsSpecificationService.findById(specificationId).getSpecification());
           subscribeUserOrderDTO.setAddress(ObjectUtil.isNotNull(subscribeUserOrderDTO.getAddressId())?litemallAddressService.findById(subscribeUserOrderDTO.getAddressId()).getAddressDetail():null);
            return subscribeUserOrderDTO;
        }).collect(Collectors.toList());*/



        List<LumiereSubscribeUser> users = lumiereSubscribeUserService.queryByUserId(userId, null, null, sort, order, null);
        List<SubscribeUserOrderDTO> finalUserOrderDtos = CollUtil.newArrayList();

        users.stream().forEach(user -> {
            LitemallShop shop = null;
            if (user.getShopId() != null) {
                shop = litemallShopService.findById(user.getShopId());
            }
            LitemallAddress address = null;
            if (user.getAddressId() != null) {
                address = litemallAddressService.findById(user.getAddressId());
            }

            LumiereSubscribeGoods goods = null;
            if (user.getSubscribeId() != null) {
                goods = lumiereSubscirbeGoodsService.querySubscribeGoodsById(user.getSubscribeId()).get(0);
            }

            LitemallGoodsSpecification specification = null;
            if (goods != null && goods.getSpecificationIds()[0] != null) {
                specification = litemallGoodsSpecificationService.findById(goods.getSpecificationIds()[0]);
            }

            List<LumiereSubscribeUserOrder> someUserOrders = null;
            if (user.getId() != null) {
                someUserOrders = lumiereSubscribeUserOrderService.queryBySubscribeUserId(user.getId());
            }

            LitemallGoods good = null;
            if (user.getGoodsId() != null) {
                good = litemallGoodsService.findById(user.getGoodsId());
            }

            if (someUserOrders != null && someUserOrders.size() != 0) {
                for (int i = 0; i < someUserOrders.size(); i++) {
                    SubscribeUserOrderDTO dto = new SubscribeUserOrderDTO();
                    dto.setUserOrderId(someUserOrders.get(i).getId());
                    dto.setGoodsName(good != null ? good.getName() : null);
                    dto.setAddress(address != null ? address.getAddressDetail() : null);
                    dto.setDeliveryStartTime(user.getDeliveryStartTime());
                    dto.setDeliveryEndTime(user.getDeliveryEndTime());
                    dto.setNumber(user.getNumber());
                    dto.setTransportType(user != null ? user.getMethod() : null);
                    dto.setSpecifications(specification != null ? specification.getSpecification() : null);
                    dto.setReceiptTime(someUserOrders.get(i).getReceiptTime());
                    dto.setShopName(shop != null ? shop.getName() : null);
                    dto.setShopId(user.getShopId());
                    dto.setStatus(someUserOrders.get(i).getStatus());
                    finalUserOrderDtos.add(dto);
                }
            }

        });
        List<SubscribeUserOrderDTO> userOrderDtos = finalUserOrderDtos.stream().sorted(Comparator.comparing(SubscribeUserOrderDTO::getStatus).
                thenComparing(SubscribeUserOrderDTO::getReceiptTime).thenComparing(SubscribeUserOrderDTO::getDeliveryStartTime)
                .reversed()).collect(Collectors.toList());

        Pageable pageable = PageRequest.of(page - 1,limit);
        return ResponseUtil.ok(PageUtil.getPageLumierePayMemberUserLogVo(pageable,userOrderDtos));
    }

    /**
     * 确认订阅
     * 页面确认，改变状态，并插入数据到litemall_order表
     *
     * @param userOrderId 用户订单id
     * @return {@link Object}
     */
    @PostMapping("confirmSubscribe")
    @LogAnno
    @Transactional
    public Object confirmSubscribe(@RequestParam Integer userOrderId) {
        //插入数据到订单表
        LumiereSubscribeUserOrder userOrder = lumiereSubscribeUserOrderService.findById(userOrderId);
        LumiereSubscribeUser subscribeUser = lumiereSubscribeUserService.findById(userOrder.getSubscribeUserId());
        List<LumiereSubscribeUserLog> ls = lumiereSubscribeUserLogService.findByUserId(subscribeUser.getId());
        LumiereSubscribeUserLog l = ls.stream().max(Comparator.comparing((LumiereSubscribeUserLog::getId))).get();
        LitemallOrder order = new LitemallOrder();

        /**
         * 设置订单项
         */
        order.setShopId(subscribeUser.getShopId());
        Integer addressId = subscribeUser.getAddressId();
        LitemallUser user = litemallUserService.findById(subscribeUser.getUserId());
        if (addressId != null) {
            LitemallAddress address = litemallAddressService.findById(addressId);
            if (address != null) {
                String addressStr = address.getCountry() + address.getProvince() + address.getCity() + address.getCounty() + address.getAddressDetail();
                order.setAddress(addressStr);
                order.setMobile(address.getTel());
                order.setConsignee(user.getNickname());
            }
        } else {
            order.setConsignee("");
            order.setMobile("");
            order.setAddress("");
        }
        order.setPayType(l.getPayType().byteValue());
        order.setPayTime(subscribeUser.getAddTime());
        order.setOrderSource(Constants.ORDER_SOURCE_SUBSCRIBE);
        order.setActualPrice(subscribeUser.getPrice());
        order.setOrderPrice(subscribeUser.getPrice());
        order.setOrderType(subscribeUser.getDeliveryMethod());
        order.setTaxPrice(subscribeUser.getTaxPrice());
        order.setOrderSn(orderService.generateOrderSn(user.getId()));
        order.setReceiptStartTime(LocalDateTime.of(LocalDate.now(), subscribeUser.getDeliveryStartTime()));
        order.setReceiptEndTime(LocalDateTime.of(LocalDate.now(), subscribeUser.getDeliveryEndTime()));
        order.setUserId(user.getId());
        order.setMessage(subscribeUser.getRemark());
        order.setFreightPrice(new BigDecimal(0.00));
        order.setCouponPrice(new BigDecimal(0.00));
        order.setIntegralPrice(new BigDecimal(0.00));
        order.setOrderStatus(Constants.ORDER_STATUS_ONGOING);
        order.setExternalId(subscribeUser.getSubscribeId());
        order.setMadeStatus((byte)0);
        Integer orderId = orderService.add(order);
        orderId = order.getId();
        /**
         * 查询订阅配置商品
         */
        LumiereSubscribeGoods lumiereSubscribeGoods = lumiereSubscirbeGoodsService.findBySubIdAndGoodId(subscribeUser.getSubscribeId(), subscribeUser.getGoodsId());
        LitemallGoods goods = litemallGoodsService.findById(subscribeUser.getGoodsId());

        if (goods != null) {
            /**
             * 设置订单商品项
             */
            LitemallOrderGoods orderGoods = new LitemallOrderGoods();
            orderGoods.setShopId(subscribeUser.getShopId());
            if (lumiereSubscribeGoods.getSpecificationIds() != null) {
                orderGoods.setSpecificationIds(lumiereSubscribeGoods.getSpecificationIds());
                /**
                 * 这里应该插入规格名数组，待修改
                 */
                List<String> specs = new ArrayList<>();
                for (int i = 0; i < lumiereSubscribeGoods.getSpecificationIds().length; i++) {
                    LitemallGoodsSpecification byId = litemallGoodsSpecificationService.findById(lumiereSubscribeGoods.getSpecificationIds()[i]);
                    if (byId != null) {
                        specs.add(byId.getSpecification());
                    }
                }
                orderGoods.setSpecifications(specs.toArray(new String[lumiereSubscribeGoods.getSpecificationIds().length]));
            }
            orderGoods.setGoodsId(goods.getId());
            orderGoods.setCategoryId(goods.getCategoryId());
            orderGoods.setGoodsName(goods.getName());
            orderGoods.setGoodsSn(goods.getGoodsSn());
            orderGoods.setOrderId(orderId);
            orderGoods.setProductId(subscribeUser.getGoodsProductId());
            orderGoods.setNumber(subscribeUser.getNumber().shortValue());
            orderGoods.setPicUrl(orderGoods.getPicUrl());
//            orderGoods.setPrice(subscribeUser.getPrice());
            orderGoods.setPrice(BigDecimal.ZERO);
            orderGoods.setTaxPrice(subscribeUser.getTaxPrice());
            litemallOrderGoodsService.add(orderGoods);
        }


        //改变状态，并关联order_id
        LumiereSubscribeUserOrder lumiereSubscribeUserOrder = new LumiereSubscribeUserOrder();
        BeanUtils.copyProperties(userOrder, lumiereSubscribeUserOrder);
        lumiereSubscribeUserOrder.setId(userOrderId);
        lumiereSubscribeUserOrder.setStatus((byte) 1);
        lumiereSubscribeUserOrder.setOrderId(order.getId());
        lumiereSubscribeUserOrder.setAddTime(LocalDateTime.now());
        lumiereSubscribeUserOrder.setUpdateTime(LocalDateTime.now());
        lumiereSubscribeUserOrderService.update(lumiereSubscribeUserOrder);

        //订阅订单确认发送系统消息
        noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER,"Subscribe order",
                "You will receive the " +  goods.getName() + " from " + order.getReceiptStartTime().toString().replace("T"," ") + " to " + order.getReceiptEndTime().toString().replace("T"," "),
                user.getId(), user);

        return ResponseUtil.ok("订阅订单已确认");
    }

    /**
     * 状态
     * 查询用户订阅状态
     *
     * @param userId 用户id
     * @param page   页面
     * @param limit  限制
     * @param sort   排序
     * @param order  订单
     * @return {@link Object}
     */
    @GetMapping("status")
    @LogAnno
    public Object status(@LoginUser Integer userId,
                         @RequestParam(defaultValue = "1") Integer page,
                         @RequestParam(defaultValue = "10") Integer limit,
                         @Sort @RequestParam(defaultValue = "add_time") String sort,
                         @Order @RequestParam(defaultValue = "desc") String order) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        IPage<LumiereSubscribe> subscribes = lumiereSubscribeService.queryAll(page, limit, sort, order,null);
        List status = subscribes.getRecords().stream().map(subscribe -> {
            List<LumiereSubscribeRule> rules = lumiereSubscribeRuleService.querySubscribeRule(subscribe.getId());
            LumiereSubscribeRule rule = rules.size() > 0 ? rules.get(0) : null;
            SubscribeStatusDTO subscribeStatus = new SubscribeStatusDTO();
            BeanUtils.copyProperties(subscribe, subscribeStatus);
            List<LumiereSubscribeUser> users = lumiereSubscribeUserService.queryByUserIdAndSubscribeId(userId, subscribe.getId());
            if (users.size() == 0) {
            } else {
                subscribeStatus.setStatus(1);
            }

            if (rule != null) {
                if (rule.getDaysTimes() != 0) {
                    subscribeStatus.setDayTimes(rule.getDaysTimes() != null ? rule.getDaysTimes() : null);
                }

                if (rule.getWeekTimes() != 0) {
                    subscribeStatus.setWeekTimes(rule.getWeekTimes() != null ? rule.getWeekTimes() : null);
                }

                if (rule.getMonthTimes() != 0) {
                    subscribeStatus.setMonthTimes(rule.getMonthTimes() != null ? rule.getMonthTimes() : null);
                }

                if (rule.getYearTimes() != 0) {
                    subscribeStatus.setYearTimes(rule.getYearTimes() != null ? rule.getYearTimes() : null);
                }
            }

            subscribeStatus.setPrice(rule != null ? rule.getPrice() : null);
            subscribeStatus.setPoint(rule != null ? rule.getPoint() : null);
            return subscribeStatus;
        }).collect(Collectors.toList());
        subscribes.setRecords(status);
        return ResponseUtil.okPage(subscribes);
    }

    /**
     * 改变商店
     * 确认订单时修改门店
     *
     * @param subscribeUserId 订阅用户id
     * @param shopId          商店id
     * @return {@link Object}
     */
    @PostMapping("changeShop")
    @LogAnno
    @Transactional
    public Object changeShop(Integer subscribeUserId, Integer shopId) {
        LumiereSubscribeUser lumiereSubscribeUser = new LumiereSubscribeUser();
        lumiereSubscribeUser.setId(subscribeUserId);
        lumiereSubscribeUser.setShopId(shopId);
        lumiereSubscribeUserService.update(lumiereSubscribeUser);
        return ResponseUtil.ok("修改门店地址成功");
    }

    /**
     * 按关键字查询
     * 查询用户信息
     *
     * @param keyword 关键字
     * @return {@link Object}
     */
    @GetMapping("/option")
    @LogAnno
    public Object queryByKeyword(String keyword) {
        return ResponseUtil.ok(litemallUserService.queryByKeyword(keyword));
    }

    /**
     * 手动生成订阅订单
     *
     * @param subscribeUserId 订阅用户id
     * @return {@link Object}
     */
    @PostMapping("ManualOrder")
    @LogAnno
    public Object ManualOrder(Integer subscribeUserId) {
        LumiereSubscribeUserOrder lumiereSubscribeUserOrder = new LumiereSubscribeUserOrder();
        lumiereSubscribeUserOrder.setOrderId(null);
        lumiereSubscribeUserOrder.setSubscribeUserId(subscribeUserId);
        lumiereSubscribeUserOrder.setReceiptTime(LocalDate.now().toString());
        lumiereSubscribeUserOrder.setStatus(Constants.SUBSCRIBE_USER_NOT_ACTIVE.byteValue());
        lumiereSubscribeUserOrder.setDeleted(false);
        lumiereSubscribeUserOrder.setAddTime(LocalDateTime.now());
        lumiereSubscribeUserOrder.setUpdateTime(LocalDateTime.now());
        lumiereSubscribeUserOrderService.add(lumiereSubscribeUserOrder);

        return ResponseUtil.ok();
    }

    /**
     * 给日志列表
     * 查询用户赠送记录
     *
     * @param userId 用户id
     * @param page   页面
     * @param limit  限制
     * @param sort   排序
     * @param order  订单
     * @return {@link Object}
     */
    @GetMapping("listGiveLog")
    @LogAnno
    public Object listGiveLog(@LoginUser Integer userId,
                              @RequestParam(defaultValue = "1") Integer page,
                              @RequestParam(defaultValue = "10") Integer limit,
                              @Sort @RequestParam(defaultValue = "add_time") String sort,
                              @Order @RequestParam(defaultValue = "desc") String order) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        List<LumiereSubscribeUserLog> logs = lumiereSubscribeUserLogService.listGiveLog(userId, 3,sort,order);
        List<LumiereSubscribeUserLogVo> vos = logs.stream().map(log -> {
            LumiereSubscribeUserLogVo vo = new LumiereSubscribeUserLogVo();
            BeanUtils.copyProperties(log, vo);
            LumiereSubscribe subscribe = null;

            if (log.getSubscribeId() != null) {
                subscribe = lumiereSubscribeService.findById(log.getSubscribeId());
            }

            if (subscribe != null) {
                vo.setPicture(subscribe.getPicture());

                if (vo.getSubscribeName() == null) {
                    vo.setSubscribeName(subscribe.getName());
                }
            }

            if(vo.getPrice()!= null){
                vo.setPrice(vo.getPrice().setScale(2));
            }

            //连接太多，需要合并成一条sql
            LumiereSubscribeUser subscribeUser = lumiereSubscribeUserService.findById(log.getSubscribeUserId());

            LitemallUser user = litemallUserService.findById(subscribeUser.getPurchaserId());
            vo.setPurcharser(user.getUsername());

            return vo;
        }).collect(Collectors.toList());

        Pageable pageable = PageRequest.of(page - 1,limit);
        return ResponseUtil.ok(PageUtil.getPageLumierePayMemberUserLogVo(pageable,vos));
//        return ResponseUtil.okList(vos);
    }

    /**
     * 让订单num被确认
     * 获取待确认的用户订阅订单
     *
     * @param userId 用户id
     * @return {@link Object}
     */
    @GetMapping("getOrderNumToBeConfirm")
    @LogAnno
    public Object getOrderNumToBeConfirm(@LoginUser Integer userId){
        if (userId == null) {
            return ResponseUtil.unlogin();
        }
        //发送系统通知还有待确认的订阅数
        Integer orderNumNotConfirm = subscribeUserOrderService.getOrderNumNotConfirm(userId);
        if(orderNumNotConfirm>0){
            noticeHelper.noticeUser(Constants.MSG_TYPE_OTHER,"Subscription confirmation","You have "+orderNumNotConfirm+" subscriptions to confirm !",userId,orderNumNotConfirm);
        }
        return ResponseUtil.ok(orderNumNotConfirm);
    }

    /**
     * 查询货物产品id
     *
     * @param shopId  商店id
     * @param goodsId 商品id
     * @return {@link Integer}
     */
    public Integer queryGoodsProductId(Integer shopId, Integer goodsId) {
        List<LitemallGoodsProduct> p = litemallGoodsProductService.queryByGidAndSid(goodsId, shopId);
        if (p.size() > 0) {
            return p.get(0).getId();
        } else {
            p = litemallGoodsProductService.queryByGidAndSid(goodsId, null);
            if(p.size() > 0){
                return  p.get(0).getId();
            }
            return null;
        }
    }

    /**
     * 得到车间区域id
     *
     * @param shopId 商店id
     * @return {@link Integer}
     */
    private Integer getShopRegionId(Integer shopId) {
        List<LitemallShopRegion> litemallShopRegions = litemallShopRegionService.queryByShopId(shopId);
        if (!CollectionUtils.isEmpty(litemallShopRegions)) {
            for (LitemallShopRegion litemallShopRegion : litemallShopRegions) {
                LitemallRegion litemallRegion = regionService.findById(litemallShopRegion.getRegionId());
                if (Constants.REGION_TYPE_CITY == litemallRegion.getType()) {
                    return litemallShopRegion.getRegionId();
                }
            }
        }
        return null;
    }

    /**
     * 得到税收价格
     *
     * @param dto dto
     * @return {@link Object}
     */
    public Object getTaxPrice(SubscribeConfirmDTO dto) {
        //查询税费价格
        Integer cityRegionId = getShopRegionId(dto.getShopId());
        //goods对应的shopId
        LitemallGoods goods = litemallGoodsService.findById(dto.getGoodsId());
        Integer shopId = goods != null ? goods.getShopId() : null;
        LitemallGoodsRegion goodRegion = goodsRegionService.findByGidAndCityId(dto.getGoodsId(), cityRegionId);
        //总店的商品shopId为空，无法找到对应的cityRegionId,无法算税
        BigDecimal taxPrice = BigDecimal.ZERO;
        if (null == goodRegion) {
            if (shopId != null) {
//                 return ResponseUtil.fail(GOODS_SHOP_INVALID, "商品不属于该店铺区域");
            } else {
                return new BigDecimal(0);
            }
        } else {
            Integer[] taxTypes = goodRegion.getTaxTypes();
            if (taxTypes.length != 0) {
//            return ResponseUtil.fail(GOODS_SHOP_REGION_TAX_NOTSET, "商品在该店铺区域未设置税费类型");
                for (int j = 0; j < taxTypes.length; j++) {
                    Integer taxType = taxTypes[j];
                    LitemallTax litemallTax = litemallTaxService.findById(taxType);
                    if (null == litemallTax) {
                        return ResponseUtil.fail(TAX_NOT_EXIST, "商品在该店铺区域设置的税费类型不存在");
                    } else if (litemallTax.getDeleted() || (!litemallTax.getEnable())) {
                        continue;
                    }

                    BigDecimal value = litemallTax.getValue();
                    BigDecimal price = dto.getPrice().multiply(value).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                    taxPrice = taxPrice.add(price);
                }
            }
        }
        return taxPrice;
    }

    /**
     * 保存日志
     *
     * @param actualPrice 实际价格
     * @param user        用户
     * @param type        类型
     * @param subscribeId 订阅id
     * @param u           u
     * @return {@link LitemallRechargeConsumption}
     */
    @Transactional
    public LitemallRechargeConsumption saveLog(BigDecimal actualPrice, LitemallUser user, Byte type,Integer subscribeId,LitemallUser u) {
        LitemallRechargeConsumption log = new LitemallRechargeConsumption();
        log.setAmount(actualPrice);
        log.setAddUserId(user.getId());
        log.setUserId(u.getId());
        log.setUsername(u.getUsername());
        log.setMobile(u.getMobile());
        log.setPoints(u.getPoints());
        log.setType(type);
        log.setUserLevel(u.getUserLevel());
        log.setAvailableAmount(u.getAvailableAmount());
        log.setOrderId(subscribeId);
        log.setOrderSource(Constants.ORDER_SOURCE_APP);
        litemallRechargeConsumptionService.add(log);
        return log;
    }

    /**
     * 日志保存礼物
     *
     * @param order   订单
     * @param card    卡
     * @param userId  用户id
     * @param content 内容
     * @param amount  量
     * @return {@link LitemallGiftCardUserLog}
     */
    @Transactional
    public LitemallGiftCardUserLog saveGiftLog(LitemallOrder order, LitemallGiftCardUser card, Integer userId, String content,BigDecimal amount) {
        LitemallGiftCardUserLog log = new LitemallGiftCardUserLog();

        if (order != null) {
            log.setOrderId(order.getId());
            log.setAmount(order.getActualPrice());
        }else{
            log.setAmount(amount);
        }
        log.setAddUserId(userId);
        log.setType(Constants.LOG_GIFTCARD_CONSUME);
        log.setCardNumber(card.getCardNumber());

        log.setCardUserId(card.getId());
        log.setContent(content);
        log.setBalance(card.getAmount());
        log.setOrderSource(Constants.ORDER_SOURCE_APP);
        log.setChangePoints(order.getPoints());
        litemallGiftCardUserLogService.add(log);
        return log;
    }

    /**
     * 把过期订阅用户
     *
     * @param users           用户
     * @param subscribeUserId 订阅用户id
     * @param startTime       开始时间
     * @return {@link LumiereSubscribeUser}
     */
    public LumiereSubscribeUser getExpiredSubscribeUser(List<LumiereSubscribeUser> users, Integer subscribeUserId,LocalDateTime startTime) {
        Integer linkId = subscribeUserId;

        //获取续约的subscribeUser
        LumiereSubscribeUser  endUser = lumiereSubscribeUserService.queryByLinkId(subscribeUserId);


        if (endUser == null) {     //下一个续约的subscribeUser不存在
            endUser = lumiereSubscribeUserService.findById(linkId);
        } else {                  //下一个续约的subscribeUser存在
            Iterator it = users.iterator();
            while (it.hasNext()) {
                LumiereSubscribeUser nextUser = (LumiereSubscribeUser) it.next();
                if (endUser != null && nextUser.getId().equals(endUser.getId())) {
                    it.remove();
                }
            }
            linkId = endUser.getId();
            endUser = getExpiredSubscribeUser(users,linkId,startTime);

        }
        endUser.setStartTime(startTime);
        return endUser;
    }

    /**
     * 更新
     * 修改订阅
     *
     * @param dto dto
     * @return {@link Object}
     */
    @PostMapping("update")
    @LogAnno
    @Transactional
    public Object update(@RequestBody SubscribeConfirmDTO dto){
        if(dto.getSubscribeUserId() == null){
            return ResponseUtil.fail("被修改的subscribeUserId不能为空");
        }

        /*LumiereSubscribeUser subscribeUser = lumiereSubscribeUserService.findById(dto.getSubscribeUserId());
        subscribeUser= generateSubscribeUser(dto.getSubscribeUserId(),dto);
        lumiereSubscribeUserService.update(subscribeUser);*/
        //查询关联的订阅
        Integer subscribeUserId = dto.getSubscribeUserId();

        LumiereSubscribeUser subscribeUser = null;

        List<LumiereSubscribeUser> users = new ArrayList<>();

        while(subscribeUserId != null){
            LumiereSubscribeUser sUser =   generateSubscribeUser(subscribeUserId,dto);
            users.add(sUser);


            //查询连带订阅用户
            subscribeUser = lumiereSubscribeUserService.findById(subscribeUserId);
            if(subscribeUser != null){
                subscribeUserId = subscribeUser.getLinkId();
            }
        }

        for (int i = 0; i < users.size(); i++) {
            lumiereSubscribeUserService.update(users.get(i));
        }
        return ResponseUtil.ok();
    }


    /**
     * 生成订阅用户
     *
     * @param subscribeUserId 订阅用户id
     * @param dto             dto
     * @return {@link LumiereSubscribeUser}
     */
    public LumiereSubscribeUser generateSubscribeUser(Integer subscribeUserId, SubscribeConfirmDTO dto){
        LumiereSubscribeUser sUser = new LumiereSubscribeUser();
        sUser.setId(subscribeUserId);
        //设置需要更改的信息
        if(dto.getGoodsId()!=null){
            sUser.setGoodsId(dto.getGoodsId());
        }

//        sUser.setGoodsProductId(queryGoodsProductId(dto.getShopId(),dto.getGoodsId()));
        if(dto.getAddressId() != null){
            sUser.setAddressId(dto.getAddressId());
        }

        if(dto.getDeliveryDays() != null && dto.getDeliveryDays().length > 0){
            sUser.setDeliveryDays(dto.getDeliveryDays());
        }

        if(dto.getTransportType() != null){
            sUser.setDeliveryMethod(dto.getTransportType());
        }

        if(dto.getDeliveryDates() != null && dto.getDeliveryDates().length > 0){
            sUser.setDeliveryDates(dto.getDeliveryDates());
        }
        sUser.setAutoSub(false);

        if(dto.getDeliveryStartTime() != null){
            sUser.setDeliveryStartTime(LocalTime.parse(dto.getDeliveryStartTime()));
        }

        if(dto.getDeliveryEndTime() != null){
            sUser.setDeliveryEndTime(LocalTime.parse(dto.getDeliveryEndTime()));
        }

        if(dto.getAutoSub() != null){
            sUser.setAutoSub(dto.getAutoSub() == 0 ? false : true);
        }
        if(dto.getShopId() != null){
            sUser.setShopId(dto.getShopId());
        }
        return sUser;
    }

}
